﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Argos.Workflows;
using Argos.WorkflowServices;
using System.Collections.Generic;
using Argos.Data.Model;

namespace Argos.Activities
{
	[Description("This activity is used in a workflow to deliver alerts to recipients for a specific target. This activity must be hosted in a target monitoring workflow in order to work properly.")]
	public partial class DeliverAlertActivity: Activity
	{
		public DeliverAlertActivity()
		{
			InitializeComponent();
		}



		#region public AlertTypes AlertType { get; set; }

		public static readonly DependencyProperty AlertTypeProperty = DependencyProperty.Register("AlertType", typeof(AlertTypes), typeof(DeliverAlertActivity));

		[Description("Specifies the type of alert to send.")]
		[ValidationOption(ValidationOption.Required)]
		public AlertTypes AlertType
		{
			get { return (AlertTypes)this.GetValue(AlertTypeProperty); }
			set { this.SetValue(AlertTypeProperty, value); }
		}

		#endregion



		#region protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

		/// <summary>
		/// Executes the activity and calls the <see cref="IAlertingService.DeliverAlert"/> method
		/// that is implemented in a workflow service.
		/// </summary>
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			// Don't have to check that monitoringWorkflow is not null here, because that is already
			// done in the Initialize method.
			ITargetMonitoringWorkflow monitoringWorkflow = this.FindParentActivity<ITargetMonitoringWorkflow>();
			

			IAlertingService alertingService = executionContext.GetService<IAlertingService>();
			if (null == alertingService)
				throw new InvalidOperationException(string.Format("The current workflow runtime does not contain a service that implements the '{0}' interface which is required in order to deliver alerts.", typeof(IAlertingService)));

			List<object> dataList = new List<object>();

			if (
				this.AlertType == AlertTypes.Failure
				&& monitoringWorkflow is ITargetFailureMonitoringWorkflow
				&& null != ((ITargetFailureMonitoringWorkflow)monitoringWorkflow).LastTestError
			)
			{
				dataList.Add(((ITargetFailureMonitoringWorkflow)monitoringWorkflow).LastTestError);
			}

			IStorageService storageService = executionContext.GetService<IStorageService>();
			if (null != storageService)
			{
				Test test = storageService.GetTargetTest(monitoringWorkflow.TargetId);
				if (null != test)
				{
					dataList.Add(new KeyValuePair<string, object>("Test Activity", test.ActivityType));
					dataList.Add(new KeyValuePair<string, object>("Execution Timeout", test.ExecutionTimeout));

					foreach (var property in test.ActivityProperties)
					{
						dataList.Add(property);
					}
				}
			}

			if (monitoringWorkflow is ITargetChangeMonitoringWorkflow)
			{
				dataList.Add(new KeyValuePair<string, object>("Current State ", ((ITargetChangeMonitoringWorkflow)monitoringWorkflow).CurrentTestState));
				dataList.Add(new KeyValuePair<string, object>("Previous State", ((ITargetChangeMonitoringWorkflow)monitoringWorkflow).PreviousTestState));
			}

			alertingService.DeliverAlert(monitoringWorkflow.TargetId, this.AlertType, dataList.ToArray());

			return ActivityExecutionStatus.Closed;
		}

		#endregion

		protected override void Initialize(IServiceProvider provider)
		{
			base.Initialize(provider);

			if (null == this.FindParentActivity<ITargetMonitoringWorkflow>())
				throw new InvalidOperationException(string.Format("The '{0}' activity can only be hosted in a workflow that implements the '{1}' interface.", this.GetType(), typeof(ITargetMonitoringWorkflow)));

		}
	}
}
